package com.one.blocks.eds.aop;

import com.one.blocks.eds.annotation.Eds;
import com.one.blocks.eds.core.LocalEdsRoutingKeyHolder;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

/**
 * @author <a href="mailto:idler41@163.com">linfuxin</a> created on 2024-03-27 17:30:01
 */
@Aspect
@Order(value = Ordered.HIGHEST_PRECEDENCE + 1)
public class EdsAspect {

    private final ExpressionParser parser = new SpelExpressionParser();

    @Pointcut(value = "@annotation(com.one.blocks.eds.annotation.Eds)")
    public void pointcut() {
    }

    @Around("pointcut() && @annotation(ds)")
    public Object around(ProceedingJoinPoint joinPoint, Eds ds) throws Throwable {
        try {
            // 先从当前方法获取，为null再从类获取
            LocalEdsRoutingKeyHolder.setKey(getEdsAnnotationVal(joinPoint, ds));
            return joinPoint.proceed();
        } finally {
            LocalEdsRoutingKeyHolder.clear();
        }
    }


    private String getEdsAnnotationVal(ProceedingJoinPoint joinPoint, Eds ds) {
        String val = ds.value();
        if ("".equals(val)) {
            // 使用默认数据源
            return null;
        }
        if (!isSpELSimple(val)) {
            return val;
        }

        Object[] args = joinPoint.getArgs();
        // spEL表达式解析
        Expression exp = parser.parseExpression(val);
        StandardEvaluationContext context = new StandardEvaluationContext();
        for (int i = 0, length = args.length; i < length; i++) {
            context.setVariable("p" + i, args[i]);
        }
        // 你可以根据需要设置context中的变量
        return (String) exp.getValue(context);
    }

    private boolean isSpELSimple(String expression) {
        return expression.startsWith("#");
    }
}
